import { Injectable, ConflictException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { HttpService } from '@nestjs/axios';
import { firstValueFrom } from 'rxjs';
import { Repository } from 'typeorm';
import * as bcrypt from 'bcrypt';
import { User } from './entities/user.entity';
import { CreateUserDto } from './dto/create-user.dto';
import { LoginUserDto } from './dto/login-user.dto';
import { JwtService } from '@nestjs/jwt';
import type { WeChatUserInfo, AccessTokenResponse } from './interfaces/wechat-user.interface';

@Injectable()
export class UserService {
  private readonly appId = process.env.WECHAT_APPID;
  private readonly appSecret = process.env.WECHAT_SECRET;
  constructor(
    private readonly httpService: HttpService,
    @InjectRepository(User)
    private usersRepository: Repository<User>,
    private jwtService: JwtService,
  ) {}
  async register(createUserDto: CreateUserDto): Promise<User> {
    // 检查账号或邮箱是否存在
    const existingUser = await this.usersRepository.findOne({
      where: [{ email: createUserDto.email }, { account: createUserDto.account }],
    });
    if (existingUser) {
      throw new ConflictException('账号或邮箱已存在');
    }
    const hashedPassword = await bcrypt.hash(createUserDto.password, 10);
    // 创建实体实例
    const newUser = this.usersRepository.create({
      ...createUserDto,
      password: hashedPassword,
    });
    // 触发INSERT语句，将数据持久化到数据库
    return this.usersRepository.save(newUser);
  }
  async login(loginUserDto: LoginUserDto): Promise<{ user: User; access_token: string }> {
    const user = await this.usersRepository.findOne({
      where: [{ email: loginUserDto.email }, { account: loginUserDto.account }],
    });
    if (!user) {
      throw new ConflictException('账号或邮箱不存在');
    }
    if (!(await bcrypt.compare(loginUserDto.password, user.password))) {
      throw new ConflictException('账号或密码错误');
    }
    const payload = { sub: user.uid, username: user.account };
    return {
      user,
      access_token: this.jwtService.sign(payload),
    };
  }
  async findById(uid: number): Promise<User | null> {
    return this.usersRepository.findOneBy({ uid });
  }
  async exchangeCodeForUserInfo(code: string): Promise<{ user: User; access_token: string }> {
    // 1. 通过code获取access_token
    const tokenUrl = `https://api.weixin.qq.com/sns/oauth2/access_token?appid=${this.appId}&secret=${this.appSecret}&code=${code}&grant_type=authorization_code`;
    /*
     * this.httpService.get(tokenUrl) 会返回一个 Observable
     * （NestJS 的 HttpService 基于 Axios 封装，默认返回 RxJS Observable）。
     * firstValueFrom(observable) 会订阅这个 Observable，并将其转换为 Promise：
     * */
    const tokenResponse = await firstValueFrom(this.httpService.get(tokenUrl));
    const { access_token, openid } = tokenResponse.data as AccessTokenResponse;

    // 2. 使用access_token和openid获取用户信息
    const userInfoUrl = `https://api.weixin.qq.com/sns/userinfo?access_token=${access_token}&openid=${openid}&lang=zh_CN`;
    const userInfoResponse = await firstValueFrom(this.httpService.get(userInfoUrl));
    const wechatUserInfo = userInfoResponse.data as WeChatUserInfo;

    // 3. 查找或创建用户（与UserService逻辑保持一致）
    let user = await this.usersRepository.findOne({
      where: { wechatOpenid: wechatUserInfo.openid },
    });
    if (!user) {
      // 创建新用户
      user = this.usersRepository.create({
        wechatOpenid: wechatUserInfo.openid,
        nickname: wechatUserInfo.nickname,
        avatar: wechatUserInfo.headimgurl,
        password: '', // 微信登录无需密码
      });
      await this.usersRepository.save(user);
    } else {
      // 更新现有用户信息
      user.nickname = wechatUserInfo.nickname;
      user.avatar = wechatUserInfo.headimgurl;
      await this.usersRepository.save(user);
    }
    // 4. 生成JWT令牌（与UserService的login方法保持一致）
    const payload = { sub: user.uid, username: user.account || user.wechatOpenid };
    const jwtToken = this.jwtService.sign(payload);

    return { user, access_token: jwtToken };
  }
}
